#include<cstdlib>
#include<iostream>
#include <memory>
#include <string>
using namespace std;

class AbstractProductA
{
public:
	virtual string GetProductAName() = 0;
	virtual int GetProductAType() = 0;
	virtual void Display() = 0;
};

class ProductA1: public AbstractProductA
{
public:
	ProductA1(string iNameStr):mType(0), mName(iNameStr){}
	string GetProductAName()
	{
		return mName;
	}
	int GetProductAType()
	{
		return mType;
	}
	 void Display()
	 {
		 cout<<"Product Name: "<< mName<< "\t Product type: "<< mType<<endl;
	 }
private:
	int mType; 
	string mName;
};
class ProductA2: public AbstractProductA
{
public:
	ProductA2(string iNameStr):mType(1), mName(iNameStr){}
	string GetProductAName()
	{
		return mName;
	}
	int GetProductAType()
	{
		return mType;
	}
	void Display()
	{
		cout<<"Product Name: "<< mName<< "\t Product type: "<< mType<<endl;
	}
private:
	int mType; 
	string mName;
};

class AbstractProductB
{
public:
	virtual string GetProductBName() = 0;
	virtual int GetProductBType() = 0;
	virtual void Display() = 0;
};

class ProductB1: public AbstractProductB
{
public:
	ProductB1(string iNameStr):mType(11), mName(iNameStr){}
	string GetProductBName()
	{
		return mName;
	}
	void Display()
	{
		cout<<"Product Name: "<< mName<< "\t Product type: "<< mType<<endl;
	}
	int GetProductBType()
	{
		return mType;
	}
private:
	int mType; 
	string mName;
};
class ProductB2: public AbstractProductB
{
public:
	ProductB2(string iNameStr):mType(12), mName(iNameStr){}
	string GetProductBName()
	{
		return mName;
	}
	int GetProductBType()
	{
		return mType;
	}
	void Display()
	{
		cout<<"Product Name: "<< mName<< "\t Product type: "<< mType<<endl;
	}
private:
	int mType; 
	string mName;
};

class AbstractFactory
{
public:
	virtual AbstractProductA* CreateProductA()=0;
	virtual AbstractProductB* CreateProductB()=0;
};

class ConcreteFactory1 :public AbstractFactory
{
	AbstractProductA* CreateProductA()
	{
		AbstractProductA* lpA= new  ProductA1("ProductAFromFactory1");

		return lpA;

	}
	AbstractProductB* CreateProductB()
	{
		AbstractProductB* lpB = new ProductB1("ProductBFromFactory1");
		return lpB;
	}
};
class ConcreteFactory2 :public AbstractFactory
{
	AbstractProductA* CreateProductA()
	{
		AbstractProductA* lpA= new  ProductA2("ProductAFromFactory1");

		return lpA;

	}
	AbstractProductB* CreateProductB()
	{
		AbstractProductB* lpB = new ProductB2("ProductBFromFactory1");
		return lpB;
	}
};

int main()
{	
	AbstractFactory* lpAbstractFactory1  = new ConcreteFactory1();
	AbstractProductA *lpA = lpAbstractFactory1->CreateProductA();
	lpA->Display();

	getchar();
}